use std::io::{Read, Seek, SeekFrom, Write};

use indicatif::{ProgressBar, ProgressStyle};
use reqwest::{blocking, StatusCode, Url};
use tempfile::NamedTempFile;

use crate::runtime::runtime::error::InternalError;
use crate::runtime::runtime::result::InternalErrorResult;

/// 下载给定url指向的资源到一个临时文件中
pub fn download(url: Url) -> InternalErrorResult<(NamedTempFile, u64)> {
    // 创建临时文件
    let mut file = NamedTempFile::new().map_err(|e| InternalError::new(format!("Could not create temporary file: {}", e.to_string())))?;

    // 下载文件
    println!("下载文件: {} -> {}", url.as_str(), file.path().to_str().unwrap());
    let mut response = blocking::get(url).map_err(|e| InternalError::new(format!("Could not download file: {}", e.to_string())))?;
    if StatusCode::OK != response.status() {
        return Err(InternalError::new(format!("Could not download file. Status code: {}", response.status().to_string())));
    }

    let content_length = response.content_length().ok_or(InternalError::new(format!("Could not download file. Content length is none")))?;

    // 进度条
    let pb = ProgressBar::new(content_length);
    pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes}").unwrap().progress_chars("=>-"));


    // 拷贝文件
    loop {
        let mut buffer: [u8; 1024] = [0; 1024];
        let us = response.read(&mut buffer).map_err(|e| InternalError::new(format!("Could not download file: {}", e.to_string())))?;
        file.write(&buffer[..us]).map_err(|e| InternalError::new(format!("Could not write to temporary file: {}", e.to_string())))?;

        pb.inc(us as u64);
        if us == 0 {
            break;
        }
    }

    // reset seek
    file.seek(SeekFrom::Start(0)).map_err(|e| InternalError::new(format!("Could not seek in temporary file: {}", e.to_string())))?;

    pb.finish();
    Ok((file, content_length))
}

#[cfg(test)]
mod tests {
    use reqwest::Url;

    #[test]
    fn test_download() {
        let url = Url::parse("https://gitee.com/Luna-CY/hui-hui/releases/download/v0.3.1/hui-hui_linux_aarch64_v0.3.1.tar.gz");
        assert_eq!(true, url.is_ok());

        let result = super::download(url.unwrap());
        assert_eq!(true, result.is_ok(), "下载文件失败: {}", result.unwrap_err());
    }
}